﻿using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ooaavee.Events;
using Ooaavee.TestTools;

namespace UnitTests
{
    /// <summary>
    /// Tests EventAssert class.
    /// </summary>
    [TestClass]
    public class EventAssertTest
    {

        #region Demo

        /// <summary>
        /// This test method demonstrates how to use <see cref="EventWatcher"/> and <see cref="EventAssert.IsEventCount(int, EventWatcher, string)"/> 
        /// together.
        /// </summary>
        [TestMethod]
        public void IsEventCountDemo()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher target = new EventWatcher(x))
            {
                x.RaiseFourEvents();
                
                EventAssert.IsEventCount(4, target, "Expected four events.");
            }            
        }

        /// <summary>
        /// This test method demonstrates how to use <see cref="EventWatcher"/> and <see cref="EventAssert.WasRaised(string, EventWatcher, string)"/> 
        /// together.
        /// </summary>
        [TestMethod]
        public void WasRaisedDemo()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher target = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                EventAssert.WasRaised("Event1", target, "Event1 was expected.");
                EventAssert.WasRaised("Event2", target, "Event2 was expected.");
                EventAssert.WasRaised("Event3", target, "Event3 was expected.");
                EventAssert.WasRaised("Event4", target, "Event4 was expected.");
            }                        
        }

        /// <summary>
        /// This test method demonstrates how to use <see cref="EventWatcher"/> and <see cref="EventAssert.WereRaisedInSequence(string[], EventWatcher, string)"/> 
        /// together.
        /// </summary>
        [TestMethod]
        public void WasNotRaisedDemo()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher target = new EventWatcher(x, "Event1", BindingFlags.Public | BindingFlags.Instance))
            {
                x.RaiseFourEvents();

                EventAssert.WasNotRaised("Event2", target, "Event2 was not expected.");
                EventAssert.WasNotRaised("Event3", target, "Event3 was not expected.");
                EventAssert.WasNotRaised("Event4", target, "Event4 was not expected.");
            }                                    
        }

        /// <summary>
        /// This test method demonstrates how to use <see cref="EventWatcher"/> and <see cref="EventAssert.WasNotRaised(string, EventWatcher, string)"/> 
        /// together.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceDemo()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher target = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                EventAssert.WereRaisedInSequence(new[] { "Event1", "Event2", "Event3", "Event4" }, target, "Something went wrong!");
            }                                                
        }

        #endregion

        /// <summary>
        /// Tests IsEventCount method.
        /// </summary>
        [TestMethod]
        public void IsEventCountTest1()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.IsEventCount(4, watcher);
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests IsEventCount method.
        /// </summary>
        [TestMethod]
        public void IsEventCountTest2()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();
           
            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.IsEventCount(100, watcher);
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.IsEventCount failed. Expected:<100>. Actual:<4>.", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests IsEventCount method.
        /// </summary>
        [TestMethod]
        public void IsEventCountTest3()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.IsEventCount(4, watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests IsEventCount method.
        /// </summary>
        [TestMethod]
        public void IsEventCountTest4()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();
           
            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.IsEventCount(100, watcher, "Something went wrong!");
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.IsEventCount failed. Expected:<100>. Actual:<4>. Something went wrong!", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasRaised method.
        /// </summary>
        [TestMethod]
        public void WasRaisedTest1()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WasRaised("Event1", watcher);
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasRaised method.
        /// </summary>
        [TestMethod]
        public void WasRaisedTest2()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.WasRaised("UnknownEventName", watcher);
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.WasRaised failed.", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasRaised method.
        /// </summary>
        [TestMethod]
        public void WasRaisedTest3()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WasRaised("Event1", watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasRaised method.
        /// </summary>
        [TestMethod]
        public void WasRaisedTest4()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.WasRaised("UnknownEventName", watcher, "Something went wrong!");
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.WasRaised failed. Something went wrong!", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasNotRaised method.
        /// </summary>
        [TestMethod]
        public void WasNotRaisedTest1()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x, "Event2", BindingFlags.Public | BindingFlags.Instance))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WasNotRaised("Event1", watcher);
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasNotRaised method.
        /// </summary>
        [TestMethod]
        public void WasNotRaisedTest2()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x, "Event2", BindingFlags.Public | BindingFlags.Instance))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.WasNotRaised("Event2", watcher);
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.WasNotRaised failed.", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasNotRaised method.
        /// </summary>
        [TestMethod]
        public void WasNotRaisedTest3()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x, "Event2", BindingFlags.Public | BindingFlags.Instance))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WasNotRaised("Event1", watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WasNotRaised method.
        /// </summary>
        [TestMethod]
        public void WasNotRaisedTest4()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x, "Event2", BindingFlags.Public | BindingFlags.Instance))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.WasNotRaised("Event2", watcher, "Something went wrong!");
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.WasNotRaised failed. Something went wrong!", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest1()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event1", "Event2", "Event3", "Event4" }, watcher) ;
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }            
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest2()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event4", "Event3", "Event2", "Event1" }, watcher);
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.WereRaisedInSequence failed. The whole sequence was <Event1>, <Event2>, <Event3> and <Event4>.", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest3()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event1" }, watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest4()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event1", "Event2" }, watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest5()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event2", "Event3" }, watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest6()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event3" }, watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest7()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event3", "Event4" }, watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest8()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event4" }, watcher, "Something went wrong!");
                }
                catch (AssertFailedException)
                {
                    Assert.Fail("AssertFailedException was not expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest9()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();
                
                bool exceptionThrown = true;
                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event4", "Event3", "Event2", "Event1" }, watcher, "Something went wrong!");
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.WereRaisedInSequence failed. The whole sequence was <Event1>, <Event2>, <Event3> and <Event4>. Something went wrong!", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }

        /// <summary>
        /// Tests WereRaisedInSequence method.
        /// </summary>
        [TestMethod]
        public void WereRaisedInSequenceTest10()
        {
            SomeClassThatRaisesEvents x = new SomeClassThatRaisesEvents();

            using (EventWatcher watcher = new EventWatcher(x))
            {
                x.RaiseFourEvents();

                bool exceptionThrown = true;
                try
                {
                    EventAssert.WereRaisedInSequence(new[] { "Event1", "Event3", "Event2", "Event4" }, watcher, "Something went wrong!");
                    exceptionThrown = false;
                }
                catch (AssertFailedException ex)
                {
                    Assert.AreEqual("EventAssert.WereRaisedInSequence failed. The whole sequence was <Event1>, <Event2>, <Event3> and <Event4>. Something went wrong!", ex.Message);
                }
                if (exceptionThrown == false)
                {
                    Assert.Fail("AssertFailedException was expected.");
                }
            }
        }
    }
}
